﻿Partial Public Class SqlInspectorPage

    Private Class SqlItem
        Dim m_event As SqlEventArgs
        Dim m_cmd As SqlCommand
        Dim m_id As Integer = 0
        Shared m_nextid As Integer = 1
        Shared m_nullitem As SqlItem = Nothing
        Public Shared Function NullItem() As SqlItem
            If m_nullitem Is Nothing Then m_nullitem = New SqlItem(New SqlEventArgs())
            Return m_nullitem
        End Function
        Private ReadOnly Property UniqueName() As String
            Get
                Return "SqlEvent" & m_id.ToString
            End Get
        End Property
        Public ReadOnly Property Name() As String
            Get
                If m_event.Name = "" Then Return UniqueName
                Return m_event.Name
            End Get
        End Property
        Public ReadOnly Property Message() As String
            Get
                If m_event.Name = "" Then Return UniqueName
                Return m_event.Message
            End Get
        End Property
        Public ReadOnly Property Command() As SqlCommand
            Get
                Return m_cmd
            End Get
        End Property
        Private Sub New() ' make inaccessible
        End Sub
        Public Sub New(ByVal e As SqlEventArgs)

            m_event = e
            m_id = m_nextid
            m_nextid += 1

            ' copy parts of the SqlCommand in case the client reuses and changes it
            If m_event.Command IsNot Nothing Then
                m_cmd = New SqlCommand(e.Command.CommandText)
                For Each p As SqlParameter In e.Command.Parameters
                    m_cmd.Parameters.Add(New SqlParameter(p.ParameterName, p.Value))
                Next
            End If

        End Sub
        Public Overrides Function ToString() As String
            Select Case m_event.Type
                Case EnumSqlEvent.eOpenSqlFilestreamError : Return Name
                Case EnumSqlEvent.eOperation : Return Name
                Case EnumSqlEvent.eCommand : Return Message
                Case Else : Return UniqueName & ":" & m_event.Type.ToString
            End Select
        End Function
    End Class

    Private Sub SqlInspectorPage_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Loaded
        AddHandler Me.Drop, AddressOf DragDropHelper.OnDrop
        AddHandler Me.DragEnter, AddressOf DragDropHelper.OnDragEnter
    End Sub

    Private Delegate Sub DlgSqlEvent(ByVal e As SqlEventArgs)
    Public Sub SqlEvent(ByVal e As SqlEventArgs)
        If Not Dispatcher.CheckAccess() Then
            Dispatcher.Invoke(Windows.Threading.DispatcherPriority.Normal, New DlgSqlEvent(AddressOf SqlEvent), e)
        Else
            Dim si As SqlItem = New SqlItem(e)
            lbxCommands.Items.Add(si)

            ' select/display the item only if it's the last in the list
            If lbxCommands.Items.Count = 1 OrElse lbxCommands.SelectedIndex = lbxCommands.Items.Count - 2 Then ShowSqlItem(si)
        End If
    End Sub

    Private Sub ShowSqlItem(ByVal si As SqlItem)
        If si Is SqlItem.NullItem Then Return

        If si.Command Is Nothing Then
            txtMessage.Text = si.Name
            SetSql(si.Message)
        Else
            ' clean up/standardize the sql command
            Dim sql As String = si.Command.CommandText.Replace(vbCrLf, " ").Replace(vbTab, " ")
            While sql.Contains("  ")
                sql = sql.Replace("  ", " ")
            End While
            While sql.Contains(";" & vbLf)
                sql = sql.Replace(";" & vbLf, ";")
            End While
            While sql.Contains("; ")
                sql = sql.Replace("; ", ";")
            End While

            sql = sql.Replace(" FROM ", vbLf & "FROM ") _
                     .Replace(" VALUES ", vbLf & "VALUES ") _
                     .Replace(" WHERE ", vbLf & "WHERE ") _
                     .Replace(" ORDER ", vbLf & "ORDER ") _
                     .Replace(" SET ", vbLf & "SET ") _
                     .Replace(";", ";" & vbLf) _
                     .Replace(", ", "," & vbLf & vbTab) _
                     .Replace(";", ";" & vbLf)

            ' split sql into lines, show in the form
            Dim lines() As String = sql.Split(vbCrLf.ToCharArray)
            Dim sb As New System.Text.StringBuilder
            For Each line As String In lines
                sb.AppendLine(line)
            Next

            ' display the parameters
            If si.Command.Parameters.Count <> 0 Then
                sb.AppendLine().AppendLine("-- Parameters --").AppendLine()
                For Each arg As SqlParameter In si.Command.Parameters
                    'lvwParameters.Items.Add(New ListViewItem(New String() {arg.ParameterName, arg.Value.ToString}))
                    sb.AppendLine(arg.ParameterName)
                    sb.Append(vbTab).AppendLine(arg.Value.ToString)
                Next
            End If

            SetSql(sb.ToString)
            If si.Message <> "" Then txtMessage.Text = si.Message

        End If
        lbxCommands.SelectedItem = si
    End Sub

    Private Sub SetSql(ByVal sql As String)
        txtSQL.Inlines.Clear()
        txtSQL.Inlines.Add(New Run(sql))
    End Sub

    Private Sub lbxCommands_SelectionChanged(ByVal sender As Object, ByVal e As System.Windows.Controls.SelectionChangedEventArgs) Handles lbxCommands.SelectionChanged
        Dim i As Integer = lbxCommands.SelectedIndex
        If i < 0 Then Return
        Dim si As SqlItem = CType(lbxCommands.Items.Item(i), SqlItem)
        ShowSqlItem(si)
    End Sub

    Private Sub btnClear_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnClear.Click
        lbxCommands.Items.Clear()
        SetSql("")
    End Sub


End Class
